#pragma once

#include <boost/thread/mutex.hpp>
#include <boostext/util/make_shared.hpp>
#include <services/future.hpp>
#include <services/provider.hpp>
#include <services/scheduler.hpp>
#include <logger/entry.hpp>

#include <engine.script/System.hpp>

#include "Script.hpp"
#include "CompilationResult.hpp"




namespace Engine
{
	namespace Edit
	{
		/**
		 * This is the compiler that is used by many components of the editor.
		 *
		 * It's only job is to compile given source code (which is done on another thread).
		 *
		 * Currently, it is forced to create its own script system instance, but this may
		 * change in the future.
		 */
		class Compiler
		{
		public:

			typedef std::map<QString, QString>            Scripts;
			typedef services::future<CompilationResult>   Compilation;
			typedef std::vector<Engine::Script::Type>     Types;

			SHARED(Compiler);

			Compiler(services::provider::ptr provider);
			virtual ~Compiler();



			/**
			 * Compiles the given list of scripts.
			 * The scripts are most possibly compiled on another thread.
			 * The returned value contains a list of all errors that came up
			 * during the compilation process.
			 */
			boost::optional<Compilation> compile(const Scripts& scripts);

			/**
			 * @returns a list of all object types, currently registered with the engine
			 */
			Types types();

		protected:

			/**
			 * Callback functions to report errors from angelscript.
			 */
			void callback(logger::entry entry);

		private:

			services::scheduler::ptr      m_scheduler;
			Engine::Script::System::ptr   m_scriptSystem;
			volatile bool                 m_compiling;

			std::vector<logger::entry>    m_messages;
		};
		///////////////////////////////////////////////////////////////////////////////////////////
	}
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
